package com.example.searchservice.repository;



import lombok.Data;
import org.springframework.data.elasticsearch.client.elc.Aggregation;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.SearchHit;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Data
public class SearchResult <T> {
    private List<T> hits;
    private long totalHits;

    private float maxScore;

    private long total;
    private int page;
    private int size;

    private Map<String, Object> aggregations;

    public SearchResult(SearchHits<T> searchHits) {
        this.hits = searchHits.getSearchHits().stream()
                .map(SearchHit::getContent)
                .collect(Collectors.toList());
        this.totalHits = searchHits.getTotalHits();
        this.maxScore = searchHits.getMaxScore();
        this.aggregations = extractAggregationsFromSearchHits(searchHits);
    }

    public int getTotalPages() {
        return size == 0 ? 1 : (int) Math.ceil((double) totalHits / size);
    }

    private Map<String, Object> extractAggregationsFromSearchHits(SearchHits<T> searchHits) {
        Map<String, Object> result = new HashMap<>();

        try {
            // 获取聚合对象
            Field aggregationsField = searchHits.getClass().getDeclaredField("aggregations");
            aggregationsField.setAccessible(true);
            Object aggregations = aggregationsField.get(searchHits);

            if (aggregations != null) {
                // 正确的方法名应该是 getAggregations() 或 aggregations()
                try {
                    Method getAggregationsMethod = aggregations.getClass().getMethod("aggregations");
                    @SuppressWarnings("unchecked")
                    Iterable<Aggregation> aggregationIterable = (Iterable<Aggregation>) getAggregationsMethod.invoke(aggregations);

                    for (Aggregation aggregation : aggregationIterable) {
                        result.put(aggregation.getName(), parseAggregationsWithReflection(aggregation));
                    }
                } catch (NoSuchMethodException e) {
                    // 尝试其他可能的方法名
                    try {
                        Method getAggregationsMethod = aggregations.getClass().getMethod("getAggregations");
                        @SuppressWarnings("unchecked")
                        Iterable<Aggregation> aggregationIterable = (Iterable<Aggregation>) getAggregationsMethod.invoke(aggregations);

                        for (Aggregation aggregation : aggregationIterable) {
                            result.put(aggregation.getName(), parseAggregationsWithReflection(aggregation));
                        }
                    } catch (NoSuchMethodException ex) {
                        result.put("error", "Cannot find aggregations method: " + ex.getMessage());
                    }
                }
            }

        } catch (Exception e) {
            result.put("error", "Failed to extract aggregations: " + e.getMessage());
        }

        return result;
    }

    private Map<String, Object> parseAggregationsWithReflection(Object aggregations) {
        Map<String, Object> result = new HashMap<>();

        try {
            // 获取聚合的Map
            java.lang.reflect.Method asMapMethod = aggregations.getClass().getMethod("asMap");
            @SuppressWarnings("unchecked")
            Map<String, Object> aggregationMap = (Map<String, Object>) asMapMethod.invoke(aggregations);

            for (Map.Entry<String, Object> entry : aggregationMap.entrySet()) {
                result.put(entry.getKey(), parseSingleAggregation(entry.getValue()));
            }

        } catch (Exception e) {
            e.printStackTrace();
            result.put("error", "Failed to parse aggregations: " + e.getMessage());
        }

        return result;
    }

    private Object parseSingleAggregation(Object aggregation) {
        Map<String, Object> aggData = new HashMap<>();

        try {
            Class<?> aggClass = aggregation.getClass();
            String className = aggClass.getSimpleName();
            aggData.put("type", className);

            // 获取聚合名称
            Method getNameMethod = aggClass.getMethod("getName");
            String name = (String) getNameMethod.invoke(aggregation);
            aggData.put("name", name);

            // 处理不同类型的聚合
            if (className.contains("ParsedTerms") || className.contains("Terms")) {
                aggData.put("buckets", parseTermsBuckets(aggregation));
            } else if (className.contains("ParsedRange") || className.contains("Range")) {
                aggData.put("buckets", parseRangeBuckets(aggregation));
            } else if (className.contains("ParsedStats") || className.contains("Stats")) {
                aggData.put("stats", parseStats(aggregation));
            } else if (className.contains("ParsedValueCount") || className.contains("ValueCount")) {
                aggData.put("value", parseValueCount(aggregation));
            } else if (className.contains("ParsedAvg") || className.contains("Avg")) {
                aggData.put("value", parseMetricAggregation(aggregation, "getValue"));
            } else if (className.contains("ParsedSum") || className.contains("Sum")) {
                aggData.put("value", parseMetricAggregation(aggregation, "getValue"));
            } else if (className.contains("ParsedMin") || className.contains("Min")) {
                aggData.put("value", parseMetricAggregation(aggregation, "getValue"));
            } else if (className.contains("ParsedMax") || className.contains("Max")) {
                aggData.put("value", parseMetricAggregation(aggregation, "getValue"));
            }

        } catch (Exception e) {
            aggData.put("error", "Failed to parse aggregation: " + e.getMessage());
        }

        return aggData;
    }

    // 解析词条聚合桶
    private List<Map<String, Object>> parseTermsBuckets(Object termsAggregation) throws Exception {
        List<Map<String, Object>> buckets = new ArrayList<>();

        Method getBucketsMethod = termsAggregation.getClass().getMethod("getBuckets");
        @SuppressWarnings("unchecked")
        List<?> bucketList = (List<?>) getBucketsMethod.invoke(termsAggregation);

        for (Object bucket : bucketList) {
            Map<String, Object> bucketData = new HashMap<>();

            // 获取桶的基本信息
            Method getKeyMethod = bucket.getClass().getMethod("getKey");
            Method getKeyAsStringMethod = bucket.getClass().getMethod("getKeyAsString");
            Method getDocCountMethod = bucket.getClass().getMethod("getDocCount");

            bucketData.put("key", getKeyMethod.invoke(bucket));
            bucketData.put("keyAsString", getKeyAsStringMethod.invoke(bucket));
            bucketData.put("docCount", getDocCountMethod.invoke(bucket));

            // 处理子聚合
            try {
                Method getAggregationsMethod = bucket.getClass().getMethod("getAggregations");
                Object subAggregations = getAggregationsMethod.invoke(bucket);

                if (subAggregations != null) {
                    Method subAsMapMethod = subAggregations.getClass().getMethod("asMap");
                    @SuppressWarnings("unchecked")
                    Map<String, Object> subAggMap = (Map<String, Object>) subAsMapMethod.invoke(subAggregations);

                    if (!subAggMap.isEmpty()) {
                        Map<String, Object> subAggs = new HashMap<>();
                        for (Map.Entry<String, Object> entry : subAggMap.entrySet()) {
                            subAggs.put(entry.getKey(), parseSingleAggregation(entry.getValue()));
                        }
                        bucketData.put("subAggregations", subAggs);
                    }
                }
            } catch (Exception e) {
                // 忽略子聚合解析错误
                bucketData.put("subAggregationError", e.getMessage());
            }

            buckets.add(bucketData);
        }

        return buckets;
    }

    // 解析范围聚合桶 - 这是你问的 parseRangeBuckets
    private List<Map<String, Object>> parseRangeBuckets(Object rangeAggregation) throws Exception {
        List<Map<String, Object>> buckets = new ArrayList<>();

        Method getBucketsMethod = rangeAggregation.getClass().getMethod("getBuckets");
        @SuppressWarnings("unchecked")
        List<?> bucketList = (List<?>) getBucketsMethod.invoke(rangeAggregation);

        for (Object bucket : bucketList) {
            Map<String, Object> bucketData = new HashMap<>();

            // 获取范围桶的信息
            Method getKeyMethod = bucket.getClass().getMethod("getKey");
            Method getFromMethod = bucket.getClass().getMethod("getFrom");
            Method getToMethod = bucket.getClass().getMethod("getTo");
            Method getDocCountMethod = bucket.getClass().getMethod("getDocCount");

            bucketData.put("key", getKeyMethod.invoke(bucket));
            bucketData.put("from", getFromMethod.invoke(bucket));
            bucketData.put("to", getToMethod.invoke(bucket));
            bucketData.put("docCount", getDocCountMethod.invoke(bucket));

            // 处理子聚合
            try {
                Method getAggregationsMethod = bucket.getClass().getMethod("getAggregations");
                Object subAggregations = getAggregationsMethod.invoke(bucket);

                if (subAggregations != null) {
                    Method subAsMapMethod = subAggregations.getClass().getMethod("asMap");
                    @SuppressWarnings("unchecked")
                    Map<String, Object> subAggMap = (Map<String, Object>) subAsMapMethod.invoke(subAggregations);

                    if (!subAggMap.isEmpty()) {
                        Map<String, Object> subAggs = new HashMap<>();
                        for (Map.Entry<String, Object> entry : subAggMap.entrySet()) {
                            subAggs.put(entry.getKey(), parseSingleAggregation(entry.getValue()));
                        }
                        bucketData.put("subAggregations", subAggs);
                    }
                }
            } catch (Exception e) {
                // 忽略子聚合解析错误
                bucketData.put("subAggregationError", e.getMessage());
            }

            buckets.add(bucketData);
        }

        return buckets;
    }

    // 解析统计聚合 - 这是你问的 parseStats
    private Map<String, Object> parseStats(Object statsAggregation) throws Exception {
        Map<String, Object> statsData = new HashMap<>();

        Method getCountMethod = statsAggregation.getClass().getMethod("getCount");
        Method getMinMethod = statsAggregation.getClass().getMethod("getMin");
        Method getMaxMethod = statsAggregation.getClass().getMethod("getMax");
        Method getAvgMethod = statsAggregation.getClass().getMethod("getAvg");
        Method getSumMethod = statsAggregation.getClass().getMethod("getSum");

        statsData.put("count", getCountMethod.invoke(statsAggregation));
        statsData.put("min", getMinMethod.invoke(statsAggregation));
        statsData.put("max", getMaxMethod.invoke(statsAggregation));
        statsData.put("avg", getAvgMethod.invoke(statsAggregation));
        statsData.put("sum", getSumMethod.invoke(statsAggregation));

        // 尝试获取扩展统计信息（如果存在）
        try {
            Method getStdDeviationMethod = statsAggregation.getClass().getMethod("getStdDeviation");
            Method getSumOfSquaresMethod = statsAggregation.getClass().getMethod("getSumOfSquares");
            Method getVarianceMethod = statsAggregation.getClass().getMethod("getVariance");

            statsData.put("stdDeviation", getStdDeviationMethod.invoke(statsAggregation));
            statsData.put("sumOfSquares", getSumOfSquaresMethod.invoke(statsAggregation));
            statsData.put("variance", getVarianceMethod.invoke(statsAggregation));
        } catch (NoSuchMethodException e) {
            // 不是扩展统计，忽略
        }

        return statsData;
    }

    // 解析值计数聚合
    private Object parseValueCount(Object valueCountAggregation) throws Exception {
        Method getValueMethod = valueCountAggregation.getClass().getMethod("getValue");
        return getValueMethod.invoke(valueCountAggregation);
    }

    // 解析指标聚合（平均值、求和、最小值、最大值）
    private Object parseMetricAggregation(Object metricAggregation, String methodName) throws Exception {
        Method getValueMethod = metricAggregation.getClass().getMethod(methodName);
        return getValueMethod.invoke(metricAggregation);
    }

}